package map;

import input.AbstractInput;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.PriorityQueue;

import tanks.ATank;
import tanks.JuniorTank;
import tanks.MiddleTank;
import tanks.PlayerTank;
import tanks.SeniorTank;
import units.BreakUnit;
import units.ConcreteUnit;
import units.GrassUnit;
import base_object.ABaseObject;
import bullet.Bullet;
import duck.ABlock;
import duck.RubberDuck;

public class Map {
	private static final int unitRows = 56;
	private static final int unitCols = 52;
	
	private ATank playerTank;
	private ABlock duck;
	private AbstractInput aI;
	private Bullet _bullet;
	
	private int count = 0;
	
	private PriorityQueue<ABaseObject> _queue = new PriorityQueue<ABaseObject>();
	private ArrayList<ABaseObject> grassList = new ArrayList<ABaseObject>();
	
	public static Map load(InputStream iS, AbstractInput aI) throws IOException {
		
		Map map = new Map();
		map.aI = aI;
		InputStreamReader input = new InputStreamReader(iS);
		BufferedReader br = new BufferedReader(input);
		String line = null;
		StringBuilder sb = new StringBuilder();
		while ((line = br.readLine()) != null)
			sb.append(line);
		input.close();
		line = null;
		
		//Temp arrays
		char[][] _tempFieldArr = new char[unitRows/2][unitCols/2];
		char[] _tempTankArr = new char[sb.length()-_tempFieldArr.length];
		
		writeFromBuilderToTempArr(_tempFieldArr, _tempTankArr, sb);
		sb = null;
		
		//Writing objects from temp arrays to list
		ABaseObject temp = null;;
		for (int i = 0; i < _tempFieldArr.length; i++) 
			for (int j = 0; j < _tempFieldArr[i].length; j++) {
				if(_tempFieldArr[i][j]!='F')
					for(int k = 0; k<2; k++)
						for(int l = 0; l<2; l++){
							temp = createElement(_tempFieldArr[i][j], i*2+k, j*2+l, map);
							if(temp!=null) {
								map.count++;
								map._queue.add(temp);
							}
						}
			}
		
		for(int i = 0; i<_tempTankArr.length; i++) {
			temp = createElement(_tempTankArr[i], 0, 0, map);
			if(temp!=null) {
				map.count++;
				map._queue.add(temp);
			}
		}
		
		_tempFieldArr = null;
		_tempTankArr = null;
		
		map.duck = new RubberDuck(map);
		map.count++;
		map._queue.add(map.duck);
		
		map.playerTank = new PlayerTank(0, 0, aI, map);
		map.count++;
		map._queue.add(map.playerTank);
		
		return map;
	}
	
	public void checkForKill() {
		for(Iterator<ABaseObject> i = _queue.iterator(); i.hasNext();) {
			ABaseObject temp = i.next();
			if((temp.getPriority()==1)&&(temp.toKill())) 
				i.remove();
		}
	}
	
	public int getCount() {
		return count;
	}
	
	public PriorityQueue<ABaseObject> getQueue() {
		return _queue;
	}
	
	public Bullet getBullet() {
		return _bullet;
	}
	
	public void setBullet(Bullet bullet) {
		_bullet = bullet;
	}
	
	public ATank getPlayerTank() {
		return playerTank;
	}
	
	public AbstractInput getInput() {
		return aI;
	}

	private static void writeFromBuilderToTempArr(char[][] tempFieldArr, char[] tempTankArr, StringBuilder sb) {
		int index = 0;
		for (int i = 0; i < unitRows/2; i++) {
			for (int j = 0; j < unitCols/2; j++, index++) 
				tempFieldArr[i][j] = sb.toString().charAt(index);
		}
		int j = 0;
		for(int i = index; i<sb.length(); i++, j++)
			tempTankArr[j] = sb.toString().charAt(i);
	}

	private static ABaseObject createElement(char ch, int i, int j, Map map) {
		switch (ch) {
		case 'G':
			//map.grassList.add(new GrassUnit(i, j, map));
			return new GrassUnit(i, j, map);
		case 'C':
			return new ConcreteUnit(i,j, map);
		case 'B':
			return new BreakUnit(i,j, map);
		case 'S':
			return new SeniorTank(i,j, map);
		case 'J':
			return new JuniorTank(i,j, map);
		case 'M':
			return new MiddleTank(i,j, map);
		}
		return null;
	}
}
